package com.gitee.wsl.reflect.func.value

import com.gitee.wsl.func.expression.Expression
import com.gitee.wsl.func.expression.visitor.ExpressionVisitor


/**
 * An immutable value wrapper.
 */
sealed interface Value<T> {
    /**
     * The wrapped value.
     */
    val unwrappedValue: T

    companion object{
        val Void = VoidValue
        val None = NoneValue
    }
}

/**
 * Nothing. This is Quarkdown's equivalent of `null`.
 */
data object None

/**
 * A value that represents a missing value.
 */
data object NoneValue : InputValue<None>, OutputValue<None> {
    override val unwrappedValue = None
    override fun <T> accept(visitor: ExpressionVisitor<T>): T =visitor.visit(this)
}

/**
 * An empty [Value] with no content.
 */
data object VoidValue : OutputValue<Unit> {
    override val unwrappedValue = Unit
}


inline fun<reified T> Value(value: T) = ValueWrapper(value)


operator fun Value<String>.plus(other: Value<String>) = Value(this.unwrappedValue + other.unwrappedValue)

@JvmName("plusNumber")
operator fun Value<Number>.plus(other: Value<Number>) = Value<Number>(this.unwrappedValue.toDouble() + other.unwrappedValue.toDouble())
operator fun Value<Number>.minus(other: Value<Number>) = Value<Number>(this.unwrappedValue.toDouble() - other.unwrappedValue.toDouble())

/**
 * An immutable value wrapper that is used in function parameters and function call arguments.
 * When used as an [Expression], its evaluated value is the same as its static wrapped value
 */
sealed interface InputValue<T> : Value<T>, Expression

/**
 * An immutable value wrapper that is used in function outputs.
 */
sealed interface OutputValue<T> : Value<T> {
    //fun <O> accept(visitor: OutputValueVisitor<O>): O
}

data class ValueWrapper<T>(
    override val unwrappedValue: T
) : InputValue<T>, OutputValue<T> {
    override fun toString(): String = unwrappedValue.toString()

    override fun <T> accept(visitor: ExpressionVisitor<T>): T = visitor.visit(this)
}
